package associationRuleMining;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import customization.Constants;
import graphguide.*;
import dataguide.*;
import evaluation.GoldSetPairs;
import evaluation.PrecisionRecall;

public class PcaConfCalculation {

	private int Numerator = 0;
	private int Denominator = 0;
	private int DenominatorOld = 0; /*I should remove it, it's for test*/

	/* String: input Entity (e.g. <Madona>), Graph Guide for input entity */
	/* auta ta static mporei na mou dimiourgisoun provlima.... */
	private static HashMap<String, GraphGuide> GraphGuides = new HashMap<String, GraphGuide>();
	private static HashMap<String, DataGuide> DataGuides = new HashMap<String, DataGuide>();

	public PcaConfCalculation() {

	}

	public void YagoImpliesXML(String folderPath) {

		String filePath = folderPath + "totalPairsSorted.txt";

		FileWriter fstream;
		BufferedWriter out = null;
		try {
			fstream = new FileWriter(folderPath + "pcaConf_YagoImpliesXML_SingleValues.txt");
			out = new BufferedWriter(fstream);
			out.write("Yago Property\tXML Path\tpcaConf\n");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try (BufferedReader br1 = new BufferedReader(new FileReader(filePath))) {

			String line;
			while ((line = br1.readLine()) != null) {
				String[] lineColumns = line.split(Constants.separatorSpace);

				if (Double.parseDouble(lineColumns[2]) < Constants.pcaConfThreshold) /* if it larger than a threshold */
																						
					break;

				Numerator = 0;
				Denominator = 0;
				DenominatorOld = 0;
				
				String B = lineColumns[0]; // B relationship : YAGO
				String r = lineColumns[1]; // r relationship : XML
				System.out.println("B:" + B + "\tr:" + r + "!");

				Iterator<Map.Entry<String, GraphGuide>> iterator = GraphGuides
						.entrySet().iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, GraphGuide> entry = iterator.next();
					String inputValue = entry.getKey();
					GraphGuide currentGraphGuide = entry.getValue();

					if (currentGraphGuide
							.getPropertyPathsInputEntitiesAndNodes()
							.containsKey(B)) {
						TreeMap<String, ArrayList<GraphNode>> inputEntityAndNodes = (TreeMap) currentGraphGuide
								.getPropertyPathsInputEntitiesAndNodes().get(B);

						ArrayList<GraphNode> YsOfB = (ArrayList<GraphNode>) inputEntityAndNodes
								.get(inputValue);
						
						HashMap<String, GraphNode> YsOfBWithoutDuplicates = new HashMap<String, GraphNode>();
						for (GraphNode graphNode : YsOfB) {
							YsOfBWithoutDuplicates.put(graphNode.normalizedName, graphNode);
						}
						
						System.out.println("Ys in " + B + " with Douplicates = "+YsOfB.size() +"  Without douplicates = "+ YsOfBWithoutDuplicates.size());

						DenominatorOld += YsOfB.size(); // ???????

						DataGuide currentDataGuide = DataGuides.get(inputValue);
					//	System.out.println("InputValue:" + inputValue);

						if (currentDataGuide.getNodeWithValuesByPathFromTheRoot
								.containsKey(r)) {
							Node node = currentDataGuide.getNodeWithValuesByPathFromTheRoot
									.get(r);
							ArrayList<ValueNode> YsOfr = node.getValues();
							
							
							HashMap<String, ValueNode> YsOfrWithoutDuplicates = new HashMap<String, ValueNode>();
							for (ValueNode valueNode : YsOfr) {
								YsOfrWithoutDuplicates.put(valueNode.normalizedValue, valueNode);
							}
							
							
							System.out.println("Ys in " + r + " with Douplicates = "+YsOfr.size() +"  Without douplicates = "+ YsOfrWithoutDuplicates.size());

					//		System.out.println("Ys of " + B);
							int found = 0;
							
							Iterator<Map.Entry<String, GraphNode>> iterator2 = YsOfBWithoutDuplicates
									.entrySet().iterator();
							while (iterator2.hasNext()) {
								Map.Entry<String, GraphNode> entry2 = iterator2.next();
								String yOfB = entry2.getKey();
					//			System.out.println("Data Value is:"+yOfB+"---");
								if(YsOfrWithoutDuplicates.containsKey(yOfB)){
				//					System.out.println("Mpike!!");
									Numerator++;
									Denominator++;
								}else{
									Denominator++;
								}
								
							}
							
							
							
							
//							for (GraphNode graphNode : YsOfB) {
//								found = 0;
//								for (ValueNode valueNode : YsOfr) {
//									/* If y == y' */
//									if (graphNode.normalizedName
//											.equals(valueNode.normalizedValue)) { 
//										Denominator++;
//										Numerator++;
//										System.out.println("\t Numerator: "
//												+ Numerator+"\tDenominator: "+Denominator);
//										System.out.println("graphNode: "
//												+ graphNode.normalizedName
//												+ "\tvalueNode: "
//												+ valueNode.normalizedValue);
//										found = 1;
//										break; // If I want duplicates I should remove this break 
//
//									}
//									
//								}
//								if(found == 0){
//									System.out.println("Y Does Not Exist! Denominator: "+Denominator);
//									Denominator++;
//								}
//							}

						} else {// property does not exist in dataguide
								// DO nothing
							System.out.println("Property " + r
									+ " Does not exist in DataGuide!");
						}

					} else { // property does not exist in graphguide
								// what?
						System.out.println("Property " + B
								+ " Does not exist in GraphGuide!");
					}

				}
				System.out.println("\n\nNumerator: " + Numerator
						+ "\tDenominator: " + Denominator+"\tDenominatorOld: "+DenominatorOld );
				float pcaConf = (float) Numerator / (float) Denominator;
				System.out.println(B + "\t Implies\t" + r
						+ "\t with PcaConf:\t" + pcaConf + "\n\n");

				out.write(B + "\t" + r + "\t" + pcaConf + "\n");
			}// while
			out.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	
	public void XMLImpliesYago(String folderPath) {

		String filePath = folderPath + "totalPairsSorted.txt";

		FileWriter fstream;
		BufferedWriter out = null;
		try {
			fstream = new FileWriter(folderPath + "pcaConf_XMLImpliesYago_SingleValues.txt");
			out = new BufferedWriter(fstream);
			out.write("XML Path\tYago Property\tpcaConf\n");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try (BufferedReader br1 = new BufferedReader(new FileReader(filePath))) {

			String line;
			while ((line = br1.readLine()) != null) {
				String[] lineColumns = line.split(Constants.separatorSpace);

				if (Double.parseDouble(lineColumns[2]) < Constants.pcaConfThreshold) /* if it larger than a threshold */
																						
					break;

				Numerator = 0;
				Denominator = 0;
				DenominatorOld = 0;
				
				String B = lineColumns[1]; // r relationship : XML
				String r = lineColumns[0]; // B relationship : YAGO
			
				System.out.println("B:" + B + "\tr:" + r + "!");

				Iterator<Map.Entry<String, GraphGuide>> iterator = GraphGuides
						.entrySet().iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, GraphGuide> entry = iterator.next();
					String inputValue = entry.getKey();
					GraphGuide currentGraphGuide = entry.getValue();

					if (currentGraphGuide
							.getPropertyPathsInputEntitiesAndNodes()
							.containsKey(r)) {
						TreeMap<String, ArrayList<GraphNode>> inputEntityAndNodes = (TreeMap) currentGraphGuide
								.getPropertyPathsInputEntitiesAndNodes().get(r);

						ArrayList<GraphNode> YsOfr = (ArrayList<GraphNode>) inputEntityAndNodes
								.get(inputValue);
						/*I create this Map to put all the values without duplicates*/
						HashMap<String, GraphNode> YsOfrWithoutDuplicates = new HashMap<String, GraphNode>();
						for (GraphNode graphNode : YsOfr) {
							YsOfrWithoutDuplicates.put(graphNode.normalizedName, graphNode);
						}
						
						
						
						System.out.println("Ys in " + r + " with Douplicates = "+YsOfr.size() +"  Without douplicates = "+ YsOfrWithoutDuplicates.size());


						DataGuide currentDataGuide = DataGuides.get(inputValue);
						System.out.println("InputValue:" + inputValue);

						if (currentDataGuide.getNodeWithValuesByPathFromTheRoot
								.containsKey(B)) {
							Node node = currentDataGuide.getNodeWithValuesByPathFromTheRoot
									.get(B);
							ArrayList<ValueNode> YsOfB = node.getValues();
							/*I create this Map to put all the values without duplicates*/
							HashMap<String, ValueNode> YsOfBWithoutDuplicates = new HashMap<String, ValueNode>();
							for (ValueNode valueNode : YsOfB) {
								YsOfBWithoutDuplicates.put(valueNode.normalizedValue, valueNode);
							}

							DenominatorOld += YsOfBWithoutDuplicates.size(); // ???????

							System.out.println("Ys in " + B + " with Douplicates = "
									+YsOfB.size()+ "  Without douplicates = " +YsOfBWithoutDuplicates.size());
					
							Iterator<Map.Entry<String, ValueNode>> iterator2 = YsOfBWithoutDuplicates
									.entrySet().iterator();
							while (iterator2.hasNext()) {
								Map.Entry<String, ValueNode> entry2 = iterator2.next();
								String yOfB = entry2.getKey();
								if(YsOfrWithoutDuplicates.containsKey(yOfB)){
									Numerator++;
									Denominator++;
								}else{
									Denominator++;
								}
							}
						} else {// property does not exist in dataguide
								// DO nothing
							System.out.println("Property " + B
									+ " Does not exist in DataGuide!");
						}

					} else { // property does not exist in graphguide
								// what?
						System.out.println("Property " + r
								+ " Does not exist in GraphGuide!");
					}

				}
				System.out.println("\n\nNumerator: " + Numerator
						+ "\tDenominator: " + Denominator+"\tDenominatorOld: "+DenominatorOld );
				float pcaConf = (float) Numerator / (float) Denominator;
				System.out.println(B + "\t Implies\t" + r
						+ "\t with PcaConf:\t" + pcaConf + "\n\n");

				out.write(B + "\t" + r + "\t" + pcaConf + "\n");
			}// while
			out.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	

	public static void createGraphGuides(String filepath) {
		try (BufferedReader br = new BufferedReader(new FileReader(filepath))) {

			String sCurrentLine;
			while ((sCurrentLine = br.readLine()) != null) {

				String[] columns = sCurrentLine
						.split(Constants.separatorForInputsFiles);
				/* GRAPH GUIDE */
				GraphGuide graphG = new GraphGuide();
				graphG.parseInputsEntitiesFile(columns[1]);

				GraphGuides.put(columns[1], graphG);
				System.out.println("New GraphGuide created:" + columns[1]);
			}// while
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void createDataGuide(String inputEntitiesType,
			String pathForFunctionResults) {
		try (BufferedReader br = new BufferedReader(new FileReader(
				Constants.getFileWithInputsForType(inputEntitiesType)))) {

			String sCurrentLine;
			while ((sCurrentLine = br.readLine()) != null) {

				String[] columns = sCurrentLine
						.split(Constants.separatorForInputsFiles);

				/* DATA GUIDE */
				DataGuide dataG = new DataGuide();
				dataG.makeparse(pathForFunctionResults
						+ columns[0].replace(" ", "+"));
				dataG.reInitMap();
				DataGuides.put(columns[1], dataG);
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		createGraphGuides(Constants.getFileWithInputsForType("singers"));
		//createGraphGuides(Constants.getFileWithInputsForType("writers"));
		System.out.println("No Of GraphGuides:" + GraphGuides.size());

		try (BufferedReader br1 = new BufferedReader(new FileReader(
				Constants.fileWithFunctionsToCall))) {

			String line;
			int tmp = 0;
			while ((line = br1.readLine()) != null) {
				if (tmp == 0) {
					tmp++;
					continue;
				}

				String[] lineColumns = line.split(Constants.separatorSpace);

				String pathForFunctionResults = Constants.projectDirectory
						+ lineColumns[0] + "/" + lineColumns[1] + "/"
						+ lineColumns[1] + "/";

				String pathToFunctionFolder = Constants.projectDirectory
						+ lineColumns[0] + "/" + lineColumns[1] + "/";

				String inputValuesType = lineColumns[2];

				DataGuides.clear();
				System.out.println("DataGuides should be zero:"
						+ DataGuides.size());

				createDataGuide(inputValuesType, pathForFunctionResults);
				System.out.println("DataGuides size:" + DataGuides.size());

				PcaConfCalculation pcaConf = new PcaConfCalculation();

				pcaConf.YagoImpliesXML(pathToFunctionFolder);
			//	pcaConf.XMLImpliesYago(pathToFunctionFolder);
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
